<template>
  <transition name="viewer-fade">
    <div @click.stop="closeLightBox" class="vue-lb-container" v-show="lightBoxOn">
      <div class="vue-lb-content">
        <div class="vue-lb-header">
          <span></span>
          <button type="button" title="关闭（Esc）" class="vue-lb-button-close">
            <span>
              <svg
                fill="white"
                x="0px"
                y="0px"
                width="100%"
                height="100%"
                viewBox="0 0 512 512"
                style="enable-background: new 0 0 512 512"
              >
                <path
                  d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4 L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1 c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1 c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z"
                ></path>
              </svg>
            </span>
          </button>
        </div>

        <div class="vue-lb-figure" @click.stop :key="animateKey">
          <div v-if="boxImages.length === 0" class="vue-lb-modal-none">{{ noText }}</div>
          <div v-else>
            <img :src="boxImages[select].src" alt="" class="vue-lb-modal-image" />
            <div class="vue-lb-info" v-show="showCaption">{{ boxImages[select].caption }}</div>
          </div>

          <div class="vue-lb-footer" v-show="showFooter">
            <div class="vue-lb-footer-info"></div>
            <div class="vue-lb-footer-count">{{ select + 1 }} / {{ countImages }}</div>
          </div>
        </div>
      </div>

      <div class="vue-lb-thumbnail" v-if="showThumbs">
        <button
          type="button"
          class="vue-lb-thumbnail-arrow vue-lb-thumbnail-left"
          title="上一个"
          @click.stop="prevImage"
        >
          <span>
            <svg fill="white" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 512 512">
              <path
                d="M213.7,256L213.7,256L213.7,256L380.9,81.9c4.2-4.3,4.1-11.4-0.2-15.8l-29.9-30.6c-4.3-4.4-11.3-4.5-15.5-0.2L131.1,247.9 c-2.2,2.2-3.2,5.2-3,8.1c-0.1,3,0.9,5.9,3,8.1l204.2,212.7c4.2,4.3,11.2,4.2,15.5-0.2l29.9-30.6c4.3-4.4,4.4-11.5,0.2-15.8 L213.7,256z"
              ></path>
            </svg>
          </span>
        </button>

        <div
          v-for="(image, index) in imagesThumb"
          :key="index"
          class="vue-lb-modal-thumbnail"
          :class="{ 'vue-lb-modal-thumbnail-active': thumbSelect === index }"
          @click.stop="showImage(index + beginThumbIndex)"
        >
          <img :src="image" alt="" width="100%" height="100%" />
        </div>

        <button
          type="button"
          class="vue-lb-thumbnail-arrow vue-lb-thumbnail-right"
          title="下一个"
          @click.stop="nextImage"
        >
          <span>
            <svg fill="white" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 512 512">
              <path
                d="M298.3,256L298.3,256L298.3,256L131.1,81.9c-4.2-4.3-4.1-11.4,0.2-15.8l29.9-30.6c4.3-4.4,11.3-4.5,15.5-0.2l204.2,212.7 c2.2,2.2,3.2,5.2,3,8.1c0.1,3-0.9,5.9-3,8.1L176.7,476.8c-4.2,4.3-11.2,4.2-15.5-0.2L131.3,446c-4.3-4.4-4.4-11.5-0.2-15.8 L298.3,256z"
              ></path>
            </svg>
          </span>
        </button>
      </div>

      <button
        type="button"
        class="vue-lb-arrow vue-lb-left"
        title="上一个"
        @click.stop="prevImage"
        v-show="boxImages.length > 1"
      >
        <span>
          <svg fill="white" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 512 512">
            <path
              d="M213.7,256L213.7,256L213.7,256L380.9,81.9c4.2-4.3,4.1-11.4-0.2-15.8l-29.9-30.6c-4.3-4.4-11.3-4.5-15.5-0.2L131.1,247.9 c-2.2,2.2-3.2,5.2-3,8.1c-0.1,3,0.9,5.9,3,8.1l204.2,212.7c4.2,4.3,11.2,4.2,15.5-0.2l29.9-30.6c4.3-4.4,4.4-11.5,0.2-15.8 L213.7,256z"
            ></path>
          </svg>
        </span>
      </button>

      <button
        type="button"
        class="vue-lb-arrow vue-lb-right"
        title="下一个"
        @click.stop="nextImage"
        v-show="boxImages.length > 1"
      >
        <span>
          <svg
            fill="white"
            x="0px"
            y="0px"
            width="100%"
            height="100%"
            viewBox="0 0 512 512"
            xml:space="preserve"
          >
            <path
              d="M298.3,256L298.3,256L298.3,256L131.1,81.9c-4.2-4.3-4.1-11.4,0.2-15.8l29.9-30.6c4.3-4.4,11.3-4.5,15.5-0.2l204.2,212.7 c2.2,2.2,3.2,5.2,3,8.1c0.1,3-0.9,5.9-3,8.1L176.7,476.8c-4.2,4.3-11.2,4.2-15.5-0.2L131.3,446c-4.3-4.4-4.4-11.5-0.2-15.8 L298.3,256z"
            ></path>
          </svg>
        </span>
      </button>
    </div>
  </transition>
</template>
<script>
export default {
  name: 'ImgPreview',
  components: {},
  props: {
    images: {
      type: Array,
      required: true,
    },

    visible: {
      type: Boolean,
      default: false,
    },

    noText: {
      type: String,
      default: '无图片',
    },

    index: {
      type: Number,
      default: 0,
    },

    showCaption: {
      type: Boolean,
      default: false,
    },

    showFooter: {
      type: Boolean,
      default: true,
    },

    showThumbs: {
      type: Boolean,
      default: true,
    },

    nThumbs: {
      type: Number,
      default: 5,
    },
  },

  data() {
    return {
      select: this.index,
      thumbSelect: this.index,
      lightBoxOn: this.visible,
      countImages: 0,
      boxImages: [],
      displayThumbs: this.images ? this.images.slice(0, this.nThumbs) : [],
      beginThumbIndex: 0,
      animateKey: 'key',
    }
  },

  computed: {
    imagesThumb() {
      return this.displayThumbs.map(({ thumb, src }) => thumb || src)
    },
  },

  watch: {
    images(val) {
      this.initImages(val)
    },
    visible(val) {
      this.lightBoxOn = val
    },
    index(val) {
      this.select = val
    },
    select() {
      let halfDown = Math.floor(this.nThumbs / 2)
      let mod = 1 - (this.nThumbs % 2)

      if (this.select <= halfDown) {
        this.$set(this, 'beginThumbIndex', 0)
        this.$set(this, 'thumbSelect', this.select)
        this.$set(this, 'displayThumbs', this.boxImages.slice(0, this.nThumbs))
      } else if (this.select >= this.countImages - halfDown) {
        this.$set(this, 'beginThumbIndex', this.countImages - this.nThumbs)
        this.$set(this, 'thumbSelect', this.nThumbs - (this.countImages - this.select))
        this.$set(this, 'displayThumbs', this.boxImages.slice(-this.nThumbs))
      } else {
        this.$set(this, 'beginThumbIndex', this.select - halfDown + mod)
        this.$set(this, 'thumbSelect', halfDown - mod)
        this.$set(
          this,
          'displayThumbs',
          this.boxImages.slice(this.select - halfDown + mod, this.select + halfDown + 1)
        )
      }

      this.animateKey = Math.ceil(Math.random() * 1e7)
    },
  },

  created() {},

  mounted() {
    this.initImages(this.images)
    document.addEventListener('keyup', this.addKeyEvent)
    this.$once('hook:beforeDestroy', () => {
      document.removeEventListener('keyup', this.addKeyEvent)
    })
  },

  methods: {
    initImages(images) {
      this.boxImages = [...images]
      if (!this.boxImages[this.select]) {
        this.$set(this, 'select', 0)
      }
      this.countImages = this.boxImages.length
      this.displayThumbs = this.boxImages.slice(0, this.nThumbs)
    },
    showImage(index = this.select) {
      this.$set(this, 'lightBoxOn', true)
      this.$emit('update:visible', true)
      this.$set(this, 'select', index)
    },
    addKeyEvent(event) {
      if (event.keyCode === 37) this.prevImage()
      if (event.keyCode === 39) this.nextImage()
      if (event.keyCode === 27) this.closeLightBox()
    },
    prevImage() {
      this.$set(this, 'select', (this.select - 1 + this.countImages) % this.countImages)
    },
    nextImage() {
      this.$set(this, 'select', (this.select + 1) % this.countImages)
    },
    closeLightBox() {
      this.$set(this, 'lightBoxOn', false)
      this.$emit('update:visible', false)
      // this.$set(this, 'select', 0)
    },
  },
}
</script>

<style scoped>
.vue-lb-container {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  position: fixed;
  padding: 10px 0;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  z-index: 2500;
  background-color: rgba(0, 0, 0, 0.8);
  -ms-flex-pack: justify;
  -webkit-box-pack: justify;
}

.vue-lb-content {
  margin-bottom: 60px;
  max-width: 1024px;
  position: relative;
}

.vue-lb-header {
  display: flex;
  justify-content: space-between;
  -ms-flex-pack: justify;
  -webkit-box-pack: justify;
  height: 40px;
}

.vue-lb-header .vue-lb-button-close {
  background: none;
  border: none;
  cursor: pointer;
  outline: none;
  position: relative;
  top: 0;
  z-index: 2;
  vertical-align: bottom;
  width: 40px;
  height: 40px;
  margin-right: -10px;
  padding: 10px;
}

.vue-lb-figure {
  margin: 0;
  display: block;
  position: relative;
}

img.vue-lb-modal-image {
  cursor: pointer;
  max-height: calc(100vh - 140px);
  display: block;
  height: auto;
  max-width: 100%;
  margin: 0 auto;
  user-select: none;
  padding: 2px;
  background-color: #fff;
}

.vue-lb-modal-none {
  height: 300px;
  width: 300px;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  font-size: 24px;
}

.vue-lb-info {
  position: absolute;
  bottom: 25px;
  color: white;
  visibility: initial;
  background-color: rgba(0, 0, 0, 0.7);
  height: 40px;
  line-height: 40px;
  padding: 0 10px;
  overflow: hidden;
  width: 100%;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.vue-lb-footer {
  display: flex;
  box-sizing: border-box;
  justify-content: space-between;
  left: 0;
  line-height: 1.42;
  padding-bottom: 5px;
  padding-left: 0;
  padding-right: 0;
  padding-top: 5px;
  cursor: auto;
  color: white;
}

.vue-lb-footer-info {
  display: block;
  flex: 1 1 0;
}

.vue-lb-footer-count {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.85em;
  padding-left: 1em;
}

.vue-lb-arrow {
  background: none;
  border: none;
  border-radius: 4px;
  user-select: none;
  cursor: pointer;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40px;
  padding: 10px;
  z-index: 1;
  user-select: none;
  outline: none;
  color: rgba(255, 255, 255, 0.5);
}

.vue-lb-arrow:hover {
  color: white;
}

.vue-lb-arrow svg {
  fill: currentColor;
}

.vue-lb-arrow.vue-lb-left {
  left: 0;
}

.vue-lb-arrow.vue-lb-right {
  right: 0;
}

.vue-lb-thumbnail {
  position: absolute;
  bottom: 10px;
  height: 50px;
  padding: 0 50px;
  text-align: center;
  white-space: nowrap;
}

.vue-lb-thumbnail-arrow {
  position: absolute;
  height: 50px;
  width: 40px;
  background: none;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  outline: none;
  user-select: none;
  padding: 10px;
  top: 50%;
  margin-top: -25px;
  color: rgba(255, 255, 255, 0.5);
}

.vue-lb-thumbnail-arrow:hover {
  color: white;
}

.vue-lb-thumbnail-arrow.vue-lb-thumbnail-left {
  left: 10px;
}

.vue-lb-thumbnail-arrow.vue-lb-thumbnail-right {
  right: 10px;
}

.vue-lb-thumbnail-arrow svg {
  fill: currentColor;
}

.vue-lb-modal-thumbnail {
  background-position: center;
  background-size: cover;
  border-radius: 2px;
  border: 1px solid hsla(0, 10%, 100%, 0.2);
  cursor: pointer;
  display: inline-block;
  width: 50px;
  height: 50px;
  margin: 2px;
  overflow: hidden;
}

.vue-lb-modal-thumbnail.vue-lb-modal-thumbnail-active {
  border-color: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 2px white;
}

@media (min-width: 500px) {
  .vue-lb-thumbnail-arrow {
    width: 40px;
  }
}

@media (min-width: 768px) {
  .vue-lb-arrow {
    width: 70px;
  }
}

.fade-enter-active,
.fade-leave-active {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  animation-fill-mode: both;
  animation: fadeInLeft 0.3s ease-out;
}

.fade-enter,
.fade-leave-active {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  animation-fill-mode: both;
  animation: fadeOutRight 0.3s ease-in;
}

@keyframes fadeInLeft {
  0% {
    opacity: 0;
    transform: translateX(-500px);
  }

  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes fadeOutRight {
  0% {
    opacity: 1;
    transform: translateX(0);
  }

  100% {
    opacity: 0;
    transform: translateX(500px);
  }
}

.viewer-fade-enter-active {
  animation: viewer-fade-in 0.3s;
}

.viewer-fade-leave-active {
  animation: viewer-fade-out 0.3s;
}

@keyframes viewer-fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes viewer-fade-out {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
</style>
